import { Injectable } from '@nestjs/common'
import { ProductEntity } from 'src/entities/product.entity'
import {
  getConnection,
  getRepository,
  InsertResult,
  Repository,
  In,
} from 'typeorm'
import { InjectRepository } from '@nestjs/typeorm'
import {
  addUserSkuDto,
  createCategoryProductDto,
  createProductDto,
  ProductSkuDataInterface,
  productSkuName,
} from './dto/product.dto'
import to from 'await-to-js'
import { queryProductDto } from './dto/query-product.dto'
import { isNotEmpty, IsNotEmpty } from '_class-validator@0.12.2@class-validator'
import { paginationDto } from './dto/pagination.dto'
import { categoryProduct } from 'src/entities/categoryProduct.entity'
import { CategoryEntity } from 'src/entities/category.entity'
import {
  ProductSkuEntity,
  userProductSkuEntity,
} from 'src/entities/productSkuEntity.entity'
import { CategoryValueEntity } from 'src/entities/categoryValue.entity'
import { UserEntity } from 'src/entities/user.entity'
@Injectable()
export class ProductService {
  constructor(
    @InjectRepository(ProductEntity)
    private readonly productRepository: Repository<ProductEntity>,
    @InjectRepository(ProductSkuEntity)
    private readonly ProductSkuRepository: Repository<ProductSkuEntity>,
    @InjectRepository(CategoryEntity)
    private readonly CategoryRepository: Repository<CategoryEntity>,
    @InjectRepository(CategoryValueEntity)
    private readonly CategoryValueRepository: Repository<CategoryValueEntity>,
    @InjectRepository(userProductSkuEntity)
    private readonly UserProductSkuRepository: Repository<userProductSkuEntity>,
  ) {}

  // 创建单个商品
  async create(body: createProductDto): Promise<[Error, ProductEntity]> {
    const product = await this.productRepository.create(body)
    const [err] = await to(this.productRepository.insert(product))
    return [err, product]
  }

  // 获取单个商品
  async getOne(id: number): Promise<[Error, ProductEntity]> {
    return await to(this.productRepository.findOne(id))
  }

  // 批量添加单个商品
  async add(body: Array<createProductDto>): Promise<[Error, String]> {
    const [err] = await to(
      getConnection()
        .createQueryBuilder()
        .insert()
        .into(ProductEntity)
        .values(body)
        .execute(),
    )
    return [err, 'success']
  }

  // 获取product表中的商品tab_name
  async getType(): Promise<[Error, Array<string>]> {
    const [err, types] = await to(
      getRepository(ProductEntity)
        .createQueryBuilder('product')
        .select('tab_name')
        .groupBy('tab_name')
        .execute(),
    )
    return [err, types.map(i => i.tab_name)]
  }

  // 分页分类查询商品列表
  async getList(
    query: queryProductDto,
  ): Promise<[Error, paginationDto<ProductEntity> | null]> {
    let qb = getRepository(ProductEntity).createQueryBuilder('product')
    const { tab_name, pageNum, pageSize, name } = query
    if (isNotEmpty(tab_name)) {
      qb.where('product.tab_name = :tab_name', { tab_name })
    }
    if (isNotEmpty(name)) {
      qb.andWhere(`product.name LIKE "%${name}%"`)
    }

    qb.skip((pageNum - 1) * pageSize).take(pageSize)

    qb.printSql()

    const [err, res] = await to(qb.getManyAndCount())
    if (err) {
      return [err, null]
    } else {
      return [err, new paginationDto(pageNum, pageSize, res[0], res[1])]
    }
  }

  // 增加商品分类列表
  async addCategoryProductList(
    body: Array<createCategoryProductDto>,
  ): Promise<[Error, InsertResult]> {
    const [err, res] = await to(
      getConnection()
        .createQueryBuilder()
        .insert()
        .into(categoryProduct)
        .values(body)
        .execute(),
    )
    return [err, res]
  }

  // 获取商品分类列表
  async getCategoryProductList(): Promise<[Error, Array<categoryProduct>]> {
    const [err, res] = await to(
      getRepository(categoryProduct)
        .createQueryBuilder()
        .select('*')
        .getRawMany(),
    )
    return [err, res]
  }

  // 获取商品分类列表
  async getProductSkuData(
    id: number,
  ): Promise<[Error, ProductSkuDataInterface]> {
    const [findProductError, product] = await to(
      this.productRepository.findOne(id, {
        relations: ['productSku'],
      }),
    )
    if (findProductError) {
      return [new Error('查询商品详情失败'), null]
    }

    let categoryIdList = isNotEmpty(product.k_ids) && product.k_ids.split(',')
    if (!categoryIdList || !categoryIdList.length)
      return [new Error('商品暂无分类'), null]

    const [categoryError, categoryList] = await to(
      this.CategoryRepository.find({
        where: categoryIdList.map(i => {
          return {
            id: i,
          }
        }),
        relations: ['categoryValue'],
      }),
    )
    if (categoryError) {
      return [new Error('查询商品分类失败'), null]
    }

    return [
      null,
      {
        product,
        categoryList,
      },
    ]
  }

  // 将商品加入用户购物车
  async editSkuToUser(
    body: addUserSkuDto,
    user: UserEntity,
  ): Promise<String | Error | userProductSkuEntity> {
    const { id, sku_id, num } = body
    const productSku = await this.ProductSkuRepository.findOne(sku_id, {
      relations: ['product'],
    })
    // 购物车页面更新某行的sku或数量等信息
    if (id) {
      const oldTar = await this.UserProductSkuRepository.findOne(id)
      const hasTar = await this.UserProductSkuRepository.findOne({
        where: { productSku, user, is_deleted: 0 },
      })
      // 编辑现有sku
      if (hasTar && hasTar.id != oldTar.id) {
        // 和其他的重复 合并数量
        const res = await this.UserProductSkuRepository.save({
          ...hasTar,
          num: Number(hasTar.num) + Number(num),
        })
        // 删除原来的sku
        await this.UserProductSkuRepository.save({
          ...oldTar,
          is_deleted: 1,
        })

        return res
      }

      // 无重复,直接更新当前
      const res = await this.UserProductSkuRepository.save({
        ...oldTar,
        productSku,
        num,
      })
      return res
    } else {
      // 商品页面增加数量
      const hasTar = await this.UserProductSkuRepository.findOne({
        where: { productSku, user, is_deleted: 0 },
      })
      if (hasTar) {
        const [err,res] = await to(
          this.UserProductSkuRepository.save({
            ...hasTar,
            num: Number(hasTar.num) + Number(num),
          }),
        )
        if (err) return err
        return res
      } else {
        const [err,res] = await to(
          this.UserProductSkuRepository.save({
            num,
            productSku,
            user,
            product: productSku.product,
          }),
        )
        if (err) return err
        return res
      }
    }
    // const [findProductSkuError, productSku] = await to(
    //   this.ProductSkuRepository.findOne(sku_id, {
    //     relations: ['product'],
    //   }),
    // )
    // if (findProductSkuError) {
    //   return new Error('查询商品sku失败')
    // }

    // const newRecord = await this.UserProductSkuRepository.create({
    //   user,
    //   productSku,
    //   product: productSku.product,
    //   num,
    // })
    // const result = await this.UserProductSkuRepository.insert(newRecord)
  }

  // 获取用户购物车信息
  async getUserSku(
    user: UserEntity,
  ): Promise<Error | Array<userProductSkuEntity>> {
    let [err, result] = await to(
      this.UserProductSkuRepository.find({
        where: {
          user,
          is_deleted: 0,
        },
        relations: ['productSku', 'product'],
      }),
    )
    if (err) return err

    for (let item of result) {
      const res = await this.CategoryValueRepository.find({
        id: In(item.productSku.v_ids.split(',').map(i => parseInt(i))),
      })
      let productSku = item.productSku as productSkuName
      productSku.v_idsName = productSku.v_ids
        .split(',')
        .map(i => {
          return res.find(catV => catV.id.toString() === i).name
        })
        .join(',')
    }
    return result
  }

  // 删除用户购物车Sku
  async deleteUserSku(
    user: UserEntity,
    idList: Array<number>,
  ): Promise<Error | string> {
    await this.UserProductSkuRepository.update(
      {
        id: In(idList),
        user,
      },
      {
        is_deleted: 1,
      },
    )
    return '删除成功'
  }
}
